home *** CD-ROM | disk | FTP | other *** search
- /*
- * proc_pol.c
- *
- * Practical Algorithms for Image Analysis
- *
- * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
- */
-
- /*
- * PROC(ess)_POLY(gon)
- *
- * polygon analysis:
- * -----------------
- * reconstruct polygon;
- * determine area by pixel counting
- * (and, in poly_moments(), by evaluating zero order moment);
- *
- * evaluate curvature energy based on Zahn chain code
- *
- * compute centroid, central moments and principal axes;
- *
- * find 2**n new vertices equi-spaced along contour
- * determine radius vector relative to centroid; shift to zero mean;
- * reconstruct angular bend function with respect to new set of vertices;
- *
- * compute power_spectrum and autocorrelation by AP FFT,
- * for angular bend function (-->tan mode)
- * for radial function (-->rad mode)
- * for both (-->all)
- * save to file (writes file for plotting by routine acmp);
- *
- * evaluate Zahn-Roskies Fourier descriptors
- * write them to file (writes file for plotting by modeplt, multiplt);
- *
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include "ip.h"
-
- #define ON_MODE 1
- #define OFF_MODE 0
- #define C_HEIGHT 10
- #define C_WIDTH 10
- #define C_COLOR 255
-
-
- #define N2_LIMIT 64L
- #define MAX_ZRFD 15L
- #define N_MOMENTS 15
- #define N_MODE_PARMS 2
-
- #define ENLARGE 1.0
- #define NOLOOP 0
- #define MAX_ROW 2048
- #define LOOP_COMPLETE 8.0
-
- #define SQ2 1.414213562
- #define ZERO 0.0
- #define FABS(a) ((a) > ZERO ? (a) : - (a))
-
- #define ON 1
- #define OFF 0
- #define SHIFT_CENTROID ON
- #define SAVE_SHAPE OFF
-
- #define EVAL_CURV_EN OFF /* evaluate curv. energy */
- #define POLY_FIT ON /* invoke Wall-Danielsson fit */
- #define SPEC_ANAL ON /* perform spectral analysis */
- #define ZAHN_ROSKIES ON /* evaluate Zahn-Roskies Fourier descript. */
- #define DRAW_BDY_ONLY OFF /* draws reconstructed polygonal contour */
-
- #define DISPLAY_DATA
-
-
- struct polygon *
- select_poly (struct polygon *poly_head, Image * imgIO, int value)
- {
- struct polygon *current_poly;
-
- int c;
- int retval;
-
- int rad_mode = OFF, tan_mode = OFF;
-
- float *s, *s_ap, *s_n2;
- float *moments;
- float *phi_k;
- float *r_n2;
-
- float *n2_phi_star;
- float *acf, *p_spec;
- int *mode_parms;
- float *a_n = NULL, *b_n = NULL;
-
- int i;
- long nv, nv2;
- long n_order;
- int n_mom = N_MOMENTS;
- int n_mp = N_MODE_PARMS;
-
- unsigned int pixel_count;
-
- double av_dirn = 0.0;
- double c_len, ap_c_len, res_c_len;
- double tot_phi;
- double curv_en, e_bend, se_bend;
- double p2a_ratio;
-
- struct Bdy bd, *bdp = &bd;
- struct spoint *hullctr;
- struct spoint cursor, *pc = &cursor;
- struct spoint *v, *v_ap, *v_n2, *v_n2h;
- struct spoint *pvc;
- int hull_area;
-
- FILE *fOut, *fOut1;
- char in_buf[IN_BUF_LEN];
-
- /*
- * cycle through list of boundary polygons
- */
- printf ("...enter n to cycle, y to select poly...\n");
- current_poly = poly_head;
- for (;;) {
- pc->x = current_poly->first_x;
- pc->y = current_poly->first_y;
- printf ("poly starting at (%d, %d) select?(y/n) ", pc->x, pc->y);
-
- if ((c = readlin (in_buf)) == 'y')
- break;
- if ((current_poly = current_poly->next_poly) == NULL) {
- printf ("At end of polygon list!! Return to first polygon? (y/n)");
- if ((c = readlin (in_buf)) == 'n')
- return (current_poly);
- else
- current_poly = poly_head;
- }
- }
-
-
- nv = current_poly->poly_points;
- nv2 = 2L;
- while (nv2 < nv)
- nv2 *= 2L;
- if (nv2 >= N2_LIMIT)
- nv2 = N2_LIMIT;
-
-
- /*
- * allocate memory
- */
- if ((v = (struct spoint *) malloc ((nv + 1) * sizeof (struct spoint))) == NULL)
- exitmess ("\n...mem allocation for v failed\n", 1);
- if ((v_ap = (struct spoint *) malloc ((nv + 1) * sizeof (struct spoint))) == NULL)
- exitmess ("\n...mem allocation for v_ap failed\n", 1);
- if ((phi_k = (float *) malloc ((nv + 1) * sizeof (float))) == NULL)
- exitmess ("\n...mem allocation for phi_k failed\n", 1);
- if ((s = (float *) malloc ((nv + 1) * sizeof (float))) == NULL)
- exitmess ("\n...mem allocation for s failed\n", 1);
- if ((s_ap = (float *) malloc ((nv + 1) * sizeof (float))) == NULL)
- exitmess ("\n...mem allocation for s_ap failed\n", 1);
-
-
- if ((moments = (float *) malloc (n_mom * sizeof (float))) == NULL)
- exitmess ("\n...mem allocation for moments failed\n", 1);
-
-
- if ((v_n2 = (struct spoint *) malloc ((nv2 + 1) * sizeof (struct spoint))) == NULL)
- exitmess ("\n...mem allocation for v_n2 failed\n", 1);
- if ((v_n2h = (struct spoint *) malloc ((nv2 / 2) * sizeof (struct spoint))) == NULL)
- exitmess ("\n...mem allocation for v_n2h failed\n", 1);
- if ((r_n2 = (float *) malloc (nv2 * sizeof (float))) == NULL)
- exitmess ("\n...mem allocation for r_n2 failed\n", 1);
- if ((s_n2 = (float *) malloc ((nv2 + 1) * sizeof (float))) == NULL)
- exitmess ("\n...mem allocation for s_n2 failed\n", 1);
-
- if ((n2_phi_star = (float *) malloc (nv2 * sizeof (float))) == NULL)
- exitmess ("\n...mem allocation for n2_phi_star failed\n", 1);
-
- if ((acf = (float *) malloc (nv2 * sizeof (float))) == NULL)
- exitmess ("\n...mem allocation for acf failed\n", 1);
- if ((p_spec = (float *) malloc (nv2 * sizeof (float))) == NULL)
- exitmess ("\n...mem allocation for p_spec failed\n", 1);
- if ((mode_parms = (int *) malloc (n_mp * sizeof (int))) == NULL)
- exitmess ("\n...mem allocation for mode_parms failed\n", 1);
-
- /*
- * evaluate arc_length and Zahn angular bend function
- */
- c_len = arc_length (current_poly->d_l_ptr, s, nv);
-
- tot_phi = angular_bend (current_poly->d_phi_ptr, phi_k, nv);
-
- /*
- * reconstruct polygon vertices
- */
- pixel_count = reconstruct_poly (current_poly->d_phi_ptr,
- current_poly->d_l_ptr, nv, v, pc,
- current_poly->first_edge_out,
- current_poly->total_delta_phi,
- imgIO, value);
-
- printf ("\n...object area (pixel count): %u", pixel_count);
-
-
- /*
- * evalate curvature energy from chain code representation
- * note:
- * to obtain robust estimates of curv_en, evaluation should really
- * not be attempted before smoothing, e. g. via polygonal approx.,
- * see below;
- */
- if (EVAL_CURV_EN == ON) {
- curv_en = curvature_energy (current_poly->d_phi_ptr,
- current_poly->d_l_ptr, nv);
- printf ("\n...chain-code derived curv. energy: %f\n", curv_en);
- }
-
- /*
- * Wall-Danielsson polygonal approximation
- */
- res_c_len = p2a_ratio = e_bend = -1.0;
- if (POLY_FIT == ON) {
- fill_bdy_structure (bdp, v, nv, tot_phi);
- hullctr = poly_hull (bdp, v_ap, av_dirn, &hull_area, imgIO, GRAY);
- printf ("\tlocation of convex hull center:");
- printf (" (%3d,%3d)\n", hullctr->x, hullctr->y);
-
- if ((nv - bdp->an) > 0) {
- printf ("\n...approx poly size: %ld\n", nv = bdp->an);
-
- v_ap = (struct spoint *) realloc (v_ap, (nv + 1) * sizeof (struct spoint));
-
- nv2 = 2L;
- while (nv2 < nv)
- nv2 *= 2L;
- }
-
- /*
- * evaluate polygon moments
- */
- pvc = poly_moments (nv, v_ap, moments, imgIO, GRAY);
- printf ("\n...centroid pos: (%3d, %3d)\n", pvc->x, pvc->y);
-
- /*
- * evaluate arc_length (partial sums of edge lengths) from set of
- * vertices for approximated polygon;
- */
- ap_c_len = vert_to_clen (v_ap, s_ap, nv);
-
- /*
- * resample new polygon at 2**n sites
- */
- n2_vert (v_ap, s_ap, nv, v_n2, nv2, imgIO, 192);
- }
- else {
- pvc = poly_moments (nv, v, moments, imgIO, GRAY);
- n2_vert (v, s, nv, v_n2, nv2, imgIO, value);
- }
-
- /*
- * evaluate contour length, global shape for resampled polygon;
- */
- printf ("\n...geom. parameters for polygon:\n");
- res_c_len = vert_to_clen (v_n2, s_n2, nv2);
- p2a_ratio = shape_parm (res_c_len, moments);
-
- /*
- * evaluate total bending energy, given by the contour integral of
- * the square of the curvature (see also spec_bend_en() in psaf.c)
- * note:
- * oversampling (generating densely spaced vertices) amplifies
- * contour noise and leads to siginificant overestimates in
- * the bending energy (easily tested with circular shapes for
- * which the expected bending energy is given by 2*PI/R)
- */
- for (i = 0; i < nv2 / 2; i++)
- *(v_n2h + i) = *(v_n2 + 2 * i);
- e_bend = cont_bend_en (v_n2h, nv2 / 2);
-
- printf (" c_len: %lf, p2a_ratio: %lf, e_bend: %lf\n",
- res_c_len, p2a_ratio, e_bend);
-
- /*
- * evaluate spectral densities
- */
- if (SPEC_ANAL == ON) {
- printf ("\n...perform radial spectral analysis?(y/n)");
- c = readlin (in_buf);
- if (c == 'y')
- rad_mode = ON;
- }
- *(mode_parms + 1) = SHIFT_CENTROID;
- if (tan_mode == ON) {
- *(mode_parms + 0) = tan_mode;
-
- vert_to_phi_star (v_n2, nv2, n2_phi_star);
-
- spec_and_corr (nv2, n2_phi_star, acf, p_spec);
-
- se_bend = spec_bend_en (nv2, p_spec, res_c_len);
- }
- if (rad_mode == ON) {
- *(mode_parms + 0) = 1 - rad_mode;
-
- /*
- * evaluate radial shape function
- */
- r_dev (pvc, v_n2, r_n2, nv2, moments, imgIO, value);
-
- #ifdef DISPLAY_DATA
- printf ("\n...output of function r_dev():\n");
- for (i = 0; i < nv; i++)
- printf (" r(%3d): %f\n", i, *(r_n2 + i));
- #endif
-
- /*
- * evaluate spectrum and (auto)correlation function of
- * radial displacement function r_n2
- */
- spec_and_corr (nv2, r_n2, acf, p_spec);
-
- se_bend = spec_bend_en (nv2, p_spec, res_c_len);
- }
-
- /*
- * write spectral data to file (.acm)
- */
- c = 0;
- printf ("\n...write file (.acm)?(y/n)");
- while ((c != 'y') && (c != 'n'))
- c = readlin (in_buf);
-
- if (c == 'y') {
- printf ("...enter fn [drive:][\\directory\\]: ");
- readlin (in_buf);
-
- if ((fOut = fopen (in_buf, "w")) == NULL) {
- printf ("\n...cannot open output file %s", in_buf);
- exit (1);
- }
-
- write_acm_file (fOut, nv2, p_spec, acf, moments, n_mom,
- mode_parms, n_mp, c_len, (double) pixel_count,
- res_c_len, p2a_ratio, e_bend);
-
- fclose (fOut);
- }
- if (ZAHN_ROSKIES == ON) {
- printf ("\n...compute Fourier descriptors(y/n)?");
- if ((c = readlin (in_buf)) == 'y') {
- for (;;) {
- printf ("\n...enter # of Fourier descriptors: ");
- readlin (in_buf);
- retval = sscanf (in_buf, "%ld", &n_order);
- if ((retval == 0) || (retval == EOF)) {
- printf ("\n...try again: ");
- printf ("...enter # of Fourier descriptors: ");
- }
- else if (n_order > MAX_ZRFD) {
- printf ("\n...current max for FD: %ld\n",
- MAX_ZRFD);
- printf ("\n...try again: ");
- printf ("...enter # of Fourier descriptors: ");
- }
- else
- break;
- }
-
- /*
- * allocate memory and evaluate Fourier descriptors
- */
- if ((a_n = (float *) calloc (MAX_ZRFD, sizeof (float))) == NULL)
- exitmess ("\n...mem alloc for a_n failed\n", 1);
- if ((b_n = (float *) calloc (MAX_ZRFD, sizeof (float))) == NULL)
- exitmess ("\n...mem alloc for b_n failed\n", 1);
-
- msdescriptors (current_poly->d_phi_ptr,
- current_poly->d_l_ptr, nv, a_n, b_n, n_order);
-
- /*
- * write descriptors to file (.fd)
- */
- c = 0;
- printf ("\n...write file (.fd)?(y/n)");
- while ((c != 'y') && (c != 'n'))
- c = readlin (in_buf);
- if (c == 'y') {
- printf ("...enter fn [drive:][\\directory\\]: ");
- readlin (in_buf);
-
- if ((fOut1 = fopen (in_buf, "w")) == NULL) {
- printf ("\n...cannot open output file %s", in_buf);
- exit (1);
- }
-
- write_fd_file (fOut1, n_order, a_n, c_len,
- (double) pixel_count, (float) p2a_ratio);
-
- fclose (fOut1);
- }
- }
- }
- printf ("\n-->polygon analysis completed<--\n");
-
- /*
- * deallocate memory
- */
- free (v);
- free (v_ap);
- free (v_n2);
- free (v_n2h);
- free (s);
- free (s_ap);
- free (s_n2);
- free (phi_k);
- free (moments);
- free (r_n2);
-
- free (n2_phi_star);
-
- free (acf);
- free (p_spec);
-
- if (ZAHN_ROSKIES == ON) {
- if (a_n != NULL)
- free (a_n);
- if (b_n != NULL)
- free (b_n);
- }
-
- return (current_poly);
- }
-